/**
 * 
 */
package fr.univ_tln.inf9.exaplanning.api.salle;

import java.io.IOException;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

import javax.swing.event.EventListenerList;

import fr.univ_tln.inf9.exaplanning.api.composante.TrainingPath;
import fr.univ_tln.inf9.exaplanning.api.db.AbstractEntity;
import fr.univ_tln.inf9.exaplanning.api.db.EntityInfo;
import fr.univ_tln.inf9.exaplanning.api.db.SessionManager;
import fr.univ_tln.inf9.exaplanning.api.salle.event.ListRoomChangedEvent;
import fr.univ_tln.inf9.exaplanning.api.salle.event.ListRoomListener;
import fr.univ_tln.inf9.exaplanning.api.salle.event.Position_xChangedEvent;
import fr.univ_tln.inf9.exaplanning.api.salle.event.Position_xListener;
import fr.univ_tln.inf9.exaplanning.api.salle.event.Position_yChangedEvent;
import fr.univ_tln.inf9.exaplanning.api.salle.event.Position_yListener;
import fr.univ_tln.inf9.exaplanning.api.salle.event.RoomAddedToListEvent;
import fr.univ_tln.inf9.exaplanning.api.salle.event.RoomRemovedToListEvent;

/**
 * @author pivi
 * @author emilien (persistence)
 */
@EntityInfo(	collections = { Room.class },
				key = "name",
				methods = { "getName", "getPosition_x", "getPosition_y" },
				rows = { "name", "coord_x", "coord_y" },
				table = "building",
				variables = { "position_x", "position_y" }) 
public class Building extends AbstractEntity {
	
	//Final car clé primaire sur la base
	private final String name;
	private float position_x;
	private float position_y;
	private List<String> rooms = new LinkedList<String>();
	
	private EventListenerList listeners;
	/**
	 * @param nom
	 * @param position_x } Utile lors de la 
	 * @param position_y } localisation géographique
	 * @throws SQLException 
	 * @throws IOException 
	 */
	public Building(String name, float position_x, float position_y) throws IOException, SQLException {
		super(true);
		this.name = name;
		this.position_x = position_x;
		this.position_y = position_y;
		
		listeners = new EventListenerList();
	}
	
	private Building(String name, float px, float py, List<String> rooms) throws IOException, SQLException {
		super(false);
		this.name = name;
		this.position_x = px;
		this.position_y = py;
		this.rooms = rooms;
		
		listeners = new EventListenerList();
	}


	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @return the position_x
	 */
	public float getPosition_x() {
		return position_x;
	}


	/**
	 * @param position_x the position_x to set
	 * firePosition_xChanged() décrit dans la partie fire
	 * alerte qu'on a modifié la postion du batîment.
	 * 
	 * Cela semble être inutile car un batîment est monté et ne bougera plus.
	 * Donc dans ce cas là nos positions seraient déclarées en final
	 * comme pour le nom.
	 * 
	 * Mais on reste souple pour pouvoir modifier de mauvaises manip de la
	 * part de l'utilisateur
	 * 
	 */
	public void setPosition_x(float position_x) {
		this.position_x = position_x;
		
		fireObjectChanged();
		firePosition_xChanged();
	}


	/**
	 * @return the position_y
	 */
	public float getPosition_y() {
		return position_y;
	}


	/**
	 * @param position_y the position_y to set
	 * 
	 * même fonctionnement pour firePosition_yChanged() 
	 * que firePosition_xChanged()
	 */
	public void setPosition_y(float position_y) {
		this.position_y = position_y;
		
		fireObjectChanged();
		firePosition_yChanged();
	}


	/**
	 * @return the rooms
	 */
	public List<String> getRooms() {
		return rooms;
	}


	/**
	 * @param rooms the rooms to set
	 * 
	 * fire qui alerte que la liste de salle a changé
	 */
	public void setRooms(List<String> rooms) {
		this.rooms = rooms;
		
		fireListRoomChanged();
	}
		
	

	/**
	 * @param arg0
	 * @return
	 * @see java.util.List#add(java.lang.Object)
	 * 
	 * fire qui alerte qu'une salle a été ajouté à la liste
	 */
	public boolean add(Room r) {
		boolean res = rooms.add(r.getId());	
		fireAddRoomToList(r.getId());
		return res;
	}




	/**
	 * @param arg0
	 * @return
	 * @see java.util.List#remove(java.lang.Object)
	 * 
	 * fire qui alerte qu'une salle a été supprimer de la liste
	 */
	public boolean remove(Object arg0) {
		boolean res = rooms.remove(arg0);
		fireRemoveRoomToList(arg0.toString());
		return res;
	}

	public String RoomstoString() {
		return "Building [rooms=" + rooms + "]";
	}
	
	
	/**
	 * Méthode de la persistance
	 * @param key
	 * @return
	 * @throws NumberFormatException
	 * @throws IOException
	 * @throws SQLException
	 */
	public static Building findByKey(String key) throws NumberFormatException, IOException, SQLException {
    	List<List<String>> data = SessionManager.getInstance().getData(Building.class, key);
    	
    	List<String> variables = data.get(0);
    	Building result = new Building(variables.get(0), Float.valueOf(variables.get(1)), Float.valueOf(variables.get(1)), data.get(1));
    	
    	return result;
	}


	/****************************************************************************************************************/
	/****************************************			LISTENER				*************************************/
	/****************************************************************************************************************/

	
	public void addPosition_xListener(Position_xListener listener){
		listeners.add(Position_xListener.class, listener);
	}
	
	public void removePosition_xListener(Position_xListener l){
		 listeners.remove(Position_xListener.class, l);
	}
	
	public void addPosition_yListener(Position_yListener listener){
		listeners.add(Position_yListener.class, listener);
	}
	
	public void removePosition_yListener(Position_yListener l){
		 listeners.remove(Position_yListener.class, l);
	}
	
	
	public void AddListRoomListener (ListRoomListener listener){
		listeners.add(ListRoomListener.class, listener);
	}
	
	public void RemoveListRoomListener (ListRoomListener listener){
		listeners.remove(ListRoomListener.class, listener);
	}
	
	
	
	/****************************************************************************************************************/
	/****************************************		Définition des fires		*************************************/
	/****************************************************************************************************************/
	public void firePosition_xChanged(){
		Position_xListener[] listenerList = (Position_xListener[])listeners.getListeners(Position_xListener.class);
		
		for(Position_xListener listener : listenerList){
			listener.Position_xChanged(new Position_xChangedEvent(this, getPosition_x()));
		}
	}
	
	private void firePosition_yChanged(){
		Position_yListener[] listenerList = (Position_yListener[])listeners.getListeners(Position_yListener.class);
		
		for(Position_yListener listener : listenerList){
			listener.Position_yChanged(new Position_yChangedEvent(this, getPosition_y()));
		}
		
	}
	
	
	private void fireListRoomChanged(){
		ListRoomListener[] listenerList = (ListRoomListener[])listeners.getListeners(ListRoomListener.class);
		
		for(ListRoomListener listener : listenerList){
			listener.ListRoomChanged(new ListRoomChangedEvent(this, getRooms()));
		}
		
	}

	
	private void fireAddRoomToList(String roomAdd){
		ListRoomListener[] listenerList = (ListRoomListener[])listeners.getListeners(ListRoomListener.class);
		
		for(ListRoomListener listener : listenerList){
			listener.RoomAddedToList(new RoomAddedToListEvent(this, roomAdd));
		}
		
	}
	
	
	private void fireRemoveRoomToList(String roomRemove){
		ListRoomListener[] listenerList = (ListRoomListener[])listeners.getListeners(ListRoomListener.class);
		
		for(ListRoomListener listener : listenerList){
			listener.RoomRemovedToList(new RoomRemovedToListEvent(this, roomRemove));
		}
		
	}
	
}
